package com.younion.common.interceptor;

 
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.struts2.ServletActionContext;
import org.springframework.beans.factory.annotation.Autowired;

import com.google.common.collect.Maps;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ActionProxy;
import com.opensymphony.xwork2.config.entities.ActionConfig;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import com.younion.business.IPermissionsService;
import com.younion.common.exception.BaseException;
import com.younion.security.ShiroFilterFactoryBean.SpringShiroFilter;
import com.younion.vo.PermissionsVO;

public class AuthenticationInterceptor extends AbstractInterceptor {

	private static final long serialVersionUID = 742285864455102141L;
	
	@Autowired
	private IPermissionsService permissionsService = null;
	
	@Autowired	
	private SpringShiroFilter shiroFilter = null;
	
	
	@Override
	public String intercept(ActionInvocation invocation) throws Exception {
		HttpServletRequest request = ServletActionContext.getRequest();
		String path = request.getRequestURI();
		if (SecurityUtils.getSubject() == null) {
			ServletActionContext.getRequest().setAttribute("tipMessage", "您还没登录或长时间没有访问了，请先登录");
			return "noLoginOrTimeout";
		}
		String methodName = invocation.getProxy().getMethod();
		if(path.contains(".action") && !isInFilterChainDefinitions(path)){
			ActionProxy proxy = invocation.getProxy();
			ActionConfig config = proxy.getConfig();
			Class classz = Class.forName(config.getClassName());
			Method method = classz.getDeclaredMethod(config.getMethodName(), null);
			if(method!=null && method.isAnnotationPresent(RequiresPermissions.class)){
				RequiresPermissions permission = method.getAnnotation(RequiresPermissions.class);
				String pName = permission.value()[0];
				PermissionsVO p = lookupPermissions(pName);
				if(!SecurityUtils.getSubject().isPermitted(pName)){
					request.setAttribute("permission", p);
					return "unauthorized";
				}
			}
			return invocation.invoke();
		}
		return invocation.invoke();
	}


	private boolean isInFilterChainDefinitions(String path){
		Map<String, String> filterChainDefinitionMap = shiroFilter.getFilterChainDefinitionMap();
		for(String action : filterChainDefinitionMap.keySet()){
			if(path.contains(action) && "anon".equalsIgnoreCase(filterChainDefinitionMap.get(action)))
					return true;
		}
		return false;
	}
	
	private PermissionsVO lookupPermissions(String name){
		Map paramMap = Maps.newHashMap();
		paramMap.put("code", name);
		Collection permissions = null;
		PermissionsVO permission = null;
		try {
			permissions = permissionsService.getByMap(paramMap);
			if(!permissions.isEmpty()){
				Iterator it = permissions.iterator();
				permission = (PermissionsVO)it.next();		
			}
		} catch (BaseException e) {
			return null;
		}
		return permission;
	}
	
	
	public IPermissionsService getPermissionsService() {
		return permissionsService;
	}


	public void setPermissionsService(IPermissionsService permissionsService) {
		this.permissionsService = permissionsService;
	}

	public SpringShiroFilter getShiroFilter() {
		return shiroFilter;
	}


	public void setShiroFilter(SpringShiroFilter shiroFilter) {
		this.shiroFilter = shiroFilter;
	}

}